#ifndef __ming_fyp_render_RendererImpl_h__
#define __ming_fyp_render_RendererImpl_h__

//------------------------------------------------------------------------------
// header includes
#include "fyp/render/Renderer.h"
#include "fyp/core/Tuple.h"
#include "fyp/core/String.h"

#include <map>

struct IDirect3DDevice9;
struct IDirect3DSurface9;
struct _D3DVIEWPORT9;

//------------------------------------------------------------------------------
namespace ming
{
namespace fyp
{
namespace render
{
	class IRenderable;
	class TScreenQuad;

	//--------------------------------------------------------------------------
	class TRendererImpl : public IRenderer
	{
	public:
		//------------------------------
		// #cstor & #dstor
		TRendererImpl(IDirect3DDevice9 *device);
		~TRendererImpl();
		
		//------------------------------
		// external operations
		virtual void* GetApiDevice();

		virtual void ClearColor(const TVec4 &color);
		virtual void ClearDepth(float depth);
		virtual void ClearStencil(unsigned char stencil);

		virtual void BeginRender();
		virtual void EndRender();

		virtual void RegisterGlobalShaderParam(size_t id, const char* semantic);
		virtual void SetGlobalShaderParam(size_t id, const TShaderParam &param);

		virtual void BindTexture(size_t channel, ITexture *texture);

		virtual void BindRenderTarget(
			IRenderedTexture *rtt0,
			IRenderedTexture *rtt1,
			IRenderedTexture *rtt2,
			IRenderedTexture *rtt3,
			bool changeDepthBuffer);

		virtual void RestoreDefaultRenderTarget();

		virtual void Render(
			IRenderable *renderable,
			const TMtx44 &worldXform,
			IShader *shader);

		virtual void RenderScreenQuad(
			IShader *shader);

	private:
		//------------------------------
		// internal attributes
		IDirect3DDevice9 *mDevice;

		IDirect3DSurface9 *mDefaultRenderTarget;
		IDirect3DSurface9 *mDefaultDepthBuf;
		_D3DVIEWPORT9 *mDefaultViewport;

		TScreenQuad *mScreenQuad;

		bool mViewProjMtxDirty;

		std::map<size_t, unsigned long> mTexFilterModeMapping;
		std::map<size_t, unsigned long> mTexAddressModeMapping;

		typedef std::map< size_t, tuple<TStr, TShaderParam> > TShaderParamRegistry;
		TShaderParamRegistry mShaderParamReg;

		//------------------------------
		// internal operations
		void InitTextureSamplerMappings();
		void InitDefaultRenderStates();
		void InitDefaultGlobalShaderParams();
		void AcquireDefaultRenderTargetSettings();

		void BindGlobalShaderParams(IShader *shader);

		template<typename T>
		T& GetShaderParam(size_t id)
		{
			return get<T>( get<1>(mShaderParamReg[id]) );
		}

		void BindSingleRenderTarget(size_t channel, IRenderedTexture *rtt, bool changeDepthBuffer);
	};
	
	//--------------------------------------------------------------------------
}
}
}


#endif	//__ming_fyp_render_RendererImpl_h__